package com.henry.base.concurrency;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class AreaCalculus2 {
    public static class NodeArea extends RecursiveTask<Double> {
        private static final double THRESHOLD=0.01;
        private static final int NUM =10;
        private static final double per = NUM*THRESHOLD;
        public static AtomicInteger counter = new AtomicInteger(0);

        private double startLoc;
        private double endLoc;

        public NodeArea(double startLoc, double endLoc) {
            this.startLoc = startLoc;
            this.endLoc = endLoc;
        }

        @Override
        protected Double compute() {
            double sum=0;
            boolean canCompute = (endLoc - startLoc-THRESHOLD/1000) <= THRESHOLD;
            if (canCompute) {
                sum = calc(startLoc, endLoc);
                counter.getAndIncrement();
                System.out.println(counter + "--> calc result between " + (startLoc) + "--" + (endLoc));

            } else {
//                double step = (endLoc - startLoc) / NUM;
                double len = endLoc-startLoc;

                if (len - per>THRESHOLD/1000) {//证明需要继续分
//                    最多分NUM份
                    double end = startLoc;
                    NodeArea task = new NodeArea(startLoc,startLoc+per);
                    NodeArea task1 = new NodeArea(startLoc+per,endLoc);
                    task.fork();
                    sum+=task.join();
                    task1.fork();
                    sum+=task1.join();
//                    for (int i = 0; i < NUM&&end<endLoc; i++) {
//                        double beg = startLoc + i * per;
//                         end =  startLoc + (i + 1) * per;
//                        if (end > endLoc||i==NUM-1)
//                            end=endLoc;
//                        NodeArea task = new NodeArea(beg,end);
//                        System.out.println("task" + (beg) + "--" + (end));
//                        task.fork();
//                        sum+=task.join();
//                    }

                }else{
                    double end = startLoc;
                    for (int i = 0; i < NUM; i++) {
                        end=startLoc + (i + 1) * THRESHOLD;
                        end = end > endLoc ? endLoc : end;
                        NodeArea task = new NodeArea(startLoc + i * THRESHOLD,end );
                        task.fork();
                        sum+=task.join();
                    }
                }
            }
            return sum;
        }

        private double calc(double startLoc, double endLoc) {
            return (1/startLoc+1/endLoc)/2*(endLoc-startLoc);
        }
    }
    public static void main(String[] args){
        NodeArea nodeArea = new NodeArea(1, 100);
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Double> result = forkJoinPool.submit(nodeArea);
        long l = System.currentTimeMillis();
        try {
            System.out.println("Final Area:"+result.get());
            long l1 = System.currentTimeMillis();
            System.out.println("The whole process consumes "+(l1-l)+"ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
}
